
#include "CBondFilter.h"

#include "../BondContainer.h"
#include "../CompanyReport.h"
#include "../SSCFETSQuote.h"
#include "../SSVContainer.h"
#include "CBondSource.h"
#include "uam/UserAccountManager.h"

CBondBankRep* CBondFilter::GetBankRep(int nIndex) {
  return CBondContainer::instance().GetBankRep(nIndex);
}

CBondBankRep* CBondFilter::GetClntRep(int nIndex) {
  return CBondContainer::instance().GetClntRep(nIndex);
}

CBondCompanyRep* CBondFilter::GetCompanyRep(int nIndex) {
  return CBondContainer::instance().GetCompanyRep(nIndex);
}

CBondCompanyRep* CBondFilter::GetBrokerMixedBPRep(int nIndex) {
  return CBondContainer::instance().GetBrokerMixedBPRep(nIndex);
}

CCFETSQuoteRep* CBondFilter::GetCFETSRep(int nIndex) {
  return CBondContainer::instance().GetCFETSQuote(nIndex);
}

int CBondFilter::GetAllBondsSize() {
  return CBondContainer::instance().GetSize();
}

CBondFilter::CBondFilter()
    : m_use_condition(true), bAll(false), m_condition(0), m_checkbonds(false) {}

void CBondFilter::SetCondition(BLHCONDITION* blh, bool bAll) {
  if (blh) {
    m_use_condition = true;
    m_condition_temp = *blh;
    m_condition = &m_condition_temp;
    this->bAll = bAll;
  } else {
    m_condition = 0;
    m_use_condition = false;
  }
}

BLHCONDITION* CBondFilter::GetCondition() { return m_condition; }

void CBondFilter::SetBrokers(const std::list<std::string>& brokers) {
  m_brokls.clear();
  m_brokls.assign(brokers.begin(), brokers.end());
}
bool CBondFilter::ProcessBond(int nTmpKey, IBrokerKeyDest* dest,
                              void* context) {
  if (nTmpKey < 0 || nTmpKey >= GetAllBondsSize()) return false;

  int added = 0;
  if (!m_use_condition) {
    std::list<std::string>::const_iterator itrbrk = m_brokls.begin();
    for (; itrbrk != m_brokls.end(); itrbrk++) {
      added++;
      dest->OnBrokerKeyFound(nTmpKey, itrbrk->c_str(), context);
    }
    return added > 0;
  }

  BLHCONDITION& condStr = *m_condition;
  char szkey[10] = {0};
  bool isAllin =
      condStr.IsPriceNeedShowFastCheck();  // 无需检查是否是有效报价,提升速度
  if (isAllin) {
    if (bAll) {
      int nSize = sizeof(condStr.nBrokId) / sizeof(UINT);
      for (int i = 0; i < nSize; i++) {
        if (condStr.nBrokId[i] == 0x00) break;
        memset(szkey, 0, sizeof(szkey));
        FMTBUF(szkey, "%d", condStr.nBrokId[i]);
        dest->OnBrokerKeyFound(nTmpKey, szkey, context);
      }
    } else {
      dest->OnBrokerKeyFound(nTmpKey, condStr.sCompanyid, context);
    }
    return true;
  }

  // 有效报价
  class BrokerCollector : public CBondCompanyRep::ApplyCallback {
    const BLHCONDITION& m_cond;
    int m_index;
    IBrokerKeyDest* m_dest;
    void* m_context;
    int m_added;
    bool m_all;

   public:
    BrokerCollector(const BLHCONDITION& condStr, int index,
                    IBrokerKeyDest* dest, void* context, bool all)
        : m_dest(dest),
          m_context(context),
          m_cond(condStr),
          m_index(index),
          m_added(0),
          m_all(all) {}
    int GetAdded() const { return m_added; }
    virtual bool DoAccess(const REPORT& rept) {
      if (m_all) {
        int nCorpID = atoi(rept.m_company_id);
        if (!CBrokerList::IsValidBroker(nCorpID)) return true;  // 过滤非Broker
      }
      if (CSSVContainer::IsPriceNeedShow(m_cond, rept, m_index)) {
        m_added++;
        m_dest->OnBrokerKeyFound(m_index, rept.m_company_id, m_context);
      }
      return true;
    }
  };

  {  // 经纪商
    CBondCompanyRep* ptmp = GetCompanyRep(nTmpKey);
    if (ptmp && ptmp->GetSize() > 0) {
      BrokerCollector collector(condStr, nTmpKey, dest, context, bAll);
      ptmp->ApplyAccess(bAll, condStr.sCompanyid, &collector);
      added += collector.GetAdded();
    }
  }
  return added > 0;
}

bool CBondFilter::ProcessBondBrokerMixedBP(int nTmpKey, IBrokerKeyDest* dest,
                                           void* context) {
  if (nTmpKey < 0 || nTmpKey >= GetAllBondsSize()) return false;

  int added = 0;
  if (!m_use_condition) {
    std::list<std::string>::const_iterator itrbrk = m_brokls.begin();
    for (; itrbrk != m_brokls.end(); itrbrk++) {
      added++;
      dest->OnBrokerKeyFound(nTmpKey, itrbrk->c_str(), context);
    }
    return added > 0;
  }

  BLHCONDITION& condStr = *m_condition;
  char szkey[10] = {0};
  bool isAllin = condStr.IsPriceNeedShowFastCheck(
      false);  // 无需检查是否是有效报价,提升速度
  if (isAllin) {
    dest->OnBrokerKeyFound(nTmpKey, szkey, context);
    return true;
  }

  // 有效报价
  class BrokerCollector : public CBondCompanyRep::ApplyCallback {
    const BLHCONDITION& m_cond;
    int m_index;
    IBrokerKeyDest* m_dest;
    void* m_context;
    int m_added;
    bool m_all;

   public:
    BrokerCollector(const BLHCONDITION& condStr, int index,
                    IBrokerKeyDest* dest, void* context, bool all)
        : m_dest(dest),
          m_context(context),
          m_cond(condStr),
          m_index(index),
          m_added(0),
          m_all(all) {}
    int GetAdded() const { return m_added; }
    virtual bool DoAccess(const REPORT& rept) {
      if (m_all) {
        int nCorpID = atoi(rept.m_company_id);
        if (!CBrokerList::IsValidBroker(nCorpID)) return true;  // 过滤非Broker
      }
      if (CSSVContainer::IsMixedBestPriceNeedShow(m_cond, rept, m_index)) {
        m_added++;
        m_dest->OnBrokerKeyFound(m_index, rept.m_company_id, m_context);
      }
      return true;
    }
  };

  {  // 经纪商
    CBondCompanyRep* ptmp = GetBrokerMixedBPRep(nTmpKey);
    if (ptmp && ptmp->GetSize() > 0) {
      BrokerCollector collector(condStr, nTmpKey, dest, context, false);
      ptmp->ApplyAccess(false, condStr.sCompanyid, &collector);
      added += collector.GetAdded();
    }
  }
  return added > 0;
}

bool CBondFilter::ProcessBondCFETS(int nType, int nTmpKey, IBrokerKeyDest* dest,
                                   void* context) {
  if (!CBondContainer::instance().IsValidIndex(nTmpKey)) return false;

  if (!m_use_condition) {
    static char sBroker[33] = {0};
    FMTBUF(sBroker, "%d", nType);
    dest->OnBrokerKeyFound(nTmpKey, sBroker, context);
    return true;
  }
  if (m_condition && m_condition->nCFETSQuoteType > CCFETSQuote::QINVALID &&
      m_condition->nCFETSQuoteType < CCFETSQuote::QMAX) {
    char sType[16] = {0};
    FMTBUF(sType, "%d", nType);
    dest->OnBrokerKeyFound(nTmpKey, sType, context);
    return true;
  }
  return false;
}

bool CBondFilter::ProcessBondCFETSDeal(int nTmpKey, IBrokerKeyDest* dest,
                                       void* context) {
  if (nTmpKey < 0 || nTmpKey >= GetAllBondsSize()) return false;

  if (!m_use_condition) {
    std::list<std::string>::const_iterator itrbrk = m_brokls.begin();
    bool ret = false;
    for (; itrbrk != m_brokls.end(); itrbrk++) {
      dest->OnBrokerKeyFound(nTmpKey, itrbrk->c_str(), context);
      ret = true;
    }
    return ret;
  }

  dest->OnBrokerKeyFound(nTmpKey, "1", context);
  return true;
}

bool CBondFilter::ProcessBondSSEFI(int nTmpKey, IBrokerKeyDest* dest,
                                   void* context) {
  int added = 0;
  if (nTmpKey < 0 || nTmpKey >= GetAllBondsSize()) return added > 0;

  if (!m_use_condition) {
    std::list<std::string>::const_iterator itrbrk = m_brokls.begin();
    for (; itrbrk != m_brokls.end(); itrbrk++) {
      added++;
      dest->OnBrokerKeyFound(nTmpKey, itrbrk->c_str(), context);
    }
    return added > 0;
  }

  BLHCONDITION& condStr = *m_condition;
  char szkey[10] = {0};
  // see CSSVContainer::SetContent;
  if (condStr.nHasFlg == 0) {  // 所有报价
    if (bAll) {                // 所有经纪商
      int nSize = sizeof(condStr.nBrokId) / sizeof(UINT);
      for (int i = 0; i < nSize; i++) {
        if (condStr.nBrokId[i] == 0x00) break;
        // 先快速检查看几个控件对应的过滤器值是否全部为空,可以避免GetCompanyInfoById的开销
        bool szkey_ok = false;
        bool need_show = condStr.IsPriceNeedShowFastCheck();
        if (!need_show) {
          szkey_ok = true;
          memset(szkey, 0, sizeof(szkey));
          FMTBUF(szkey, "%d", condStr.nBrokId[i]);
          REPORT rpt = {0};
          if (CBondContainer::instance().GetCompanyInfoById(szkey, nTmpKey,
                                                            rpt)) {
            if (CSSVContainer::IsPriceNeedShow(
                    condStr, rpt, nTmpKey,
                    false))  // 无需检查是否是有效报价,提升速度
            {
              need_show = true;
            }
          }
        }
        if (need_show) {
          if (!szkey_ok) {
            memset(szkey, 0, sizeof(szkey));
            FMTBUF(szkey, "%d", condStr.nBrokId[i]);
          }
          added++;
          dest->OnBrokerKeyFound(nTmpKey, szkey, context);
        }
      }
    } else {  // 单个经纪商
      added++;
      dest->OnBrokerKeyFound(nTmpKey, condStr.sCompanyid, context);
    }
    return added > 0;
  }

  // 有效报价
  class BrokerCollector : public CBondCompanyRep::ApplyCallback {
    const BLHCONDITION& m_cond;
    int m_index;
    IBrokerKeyDest* m_dest;
    void* m_context;
    int m_added;
    bool m_all;

   public:
    BrokerCollector(const BLHCONDITION& condStr, int index,
                    IBrokerKeyDest* dest, void* context, bool all)
        : m_dest(dest),
          m_context(context),
          m_cond(condStr),
          m_index(index),
          m_added(0),
          m_all(all) {}
    int GetAdded() const { return m_added; }
    virtual bool DoAccess(const REPORT& rept) {
      if (m_all) {
        int nCorpID = atoi(rept.m_company_id);
        if (!CBrokerList::IsValidBroker(nCorpID)) return true;  // 过滤非Broker
      }
      if (CSSVContainer::IsPriceNeedShow(m_cond, rept, m_index)) {
        m_added++;
        m_dest->OnBrokerKeyFound(m_index, rept.m_company_id, m_context);
      }
      return true;
    }
  };

  {  // 经纪商
    CBondCompanyRep* ptmp = GetCompanyRep(nTmpKey);
    if (ptmp && ptmp->GetSize() > 0) {
      BrokerCollector collector(condStr, nTmpKey, dest, context, bAll);
      ptmp->ApplyAccess(bAll, condStr.sCompanyid, &collector);
      added += collector.GetAdded();
    }
  }

  return added > 0;
}

void CBondFilter::BeforeReloads() {
  if (m_checkbonds) {
  }
}
void CBondFilter::AfterReloads() {}
void CBondFilter::CheckBonds(int bid) {
  if (m_checkbonds) {
    map<int, CBondInfo>::iterator it = m_listedbonds.find(bid);
    if (it == m_listedbonds.end()) return;
    CBondInfo& bi = it->second;
    const char* key = bi.GetBondKey();
  }
}